package config

import (
	"time"
)

// Config defines the configuration structure.
type Config struct {
	General struct {
		LogLevel                  int    `mapstructure:"log_level"`
		LogToSyslog               bool   `mapstructure:"log_to_syslog"`
		PasswordHashIterations    int    `mapstructure:"password_hash_iterations"`
		GRPCDefaultResolverScheme string `mapstructure:"grpc_default_resolver_scheme"`
	} `mapstructure:"general"`

	PostgreSQL struct {
		DSN                string `mapstructure:"dsn"`
		Automigrate        bool
		MaxOpenConnections int `mapstructure:"max_open_connections"`
		MaxIdleConnections int `mapstructure:"max_idle_connections"`
	} `mapstructure:"postgresql"`

	Redis struct {
		URL        string   `mapstructure:"url"` // deprecated
		Servers    []string `mapstructure:"servers"`
		Cluster    bool     `mapstructure:"cluster"`
		MasterName string   `mapstructure:"master_name"`
		PoolSize   int      `mapstructure:"pool_size"`
		Password   string   `mapstructure:"password"`
		Database   int      `mapstructure:"database"`
		TLSEnabled bool     `mapstructure:"tls_enabled"`
		KeyPrefix  string   `mapstructure:"key_prefix"`
	} `mapstructure:"redis"`

	ApplicationServer struct {
		ID string `mapstructure:"id"`

		Codec struct {
			JS struct {
				MaxExecutionTime time.Duration `mapstructure:"max_execution_time"`
			} `mapstructure:"js"`
		} `mapstructure:"codec"`

		Integration struct {
			Marshaler string                `mapstructure:"marshaler"`
			Backend   string                `mapstructure:"backend"` // deprecated
			Enabled   []string              `mapstructure:"enabled"`
			MQTT      IntegrationMQTTConfig `mapstructure:"mqtt"`
		} `mapstructure:"integration"`

		API struct {
			Bind       string
			CACert     string `mapstructure:"ca_cert"`
			TLSCert    string `mapstructure:"tls_cert"`
			TLSKey     string `mapstructure:"tls_key"`
			PublicHost string `mapstructure:"public_host"`
		} `mapstructure:"api"`

		ExternalAPI struct {
			Bind            string
			TLSCert         string `mapstructure:"tls_cert"`
			TLSKey          string `mapstructure:"tls_key"`
			JWTSecret       string `mapstructure:"jwt_secret"`
			CORSAllowOrigin string `mapstructure:"cors_allow_origin"`
		} `mapstructure:"external_api"`
	} `mapstructure:"application_server"`

	JoinServer struct {
		Bind    string
		CACert  string `mapstructure:"ca_cert"`
		TLSCert string `mapstructure:"tls_cert"`
		TLSKey  string `mapstructure:"tls_key"`

		KEK struct {
			ASKEKLabel string `mapstructure:"as_kek_label"`

			Set []struct {
				Label string `mapstructure:"label"`
				KEK   string `mapstructure:"kek"`
			}
		} `mapstructure:"kek"`
	} `mapstructure:"join_server"`

	Metrics struct {
		Timezone string `mapstructure:"timezone"`
		Redis    struct {
			AggregationIntervals []string      `mapstructure:"aggregation_intervals"`
			MinuteAggregationTTL time.Duration `mapstructure:"minute_aggregation_ttl"`
			HourAggregationTTL   time.Duration `mapstructure:"hour_aggregation_ttl"`
			DayAggregationTTL    time.Duration `mapstructure:"day_aggregation_ttl"`
			MonthAggregationTTL  time.Duration `mapstructure:"month_aggregation_ttl"`
		} `mapstructure:"redis"`
		Prometheus struct {
			EndpointEnabled    bool   `mapstructure:"endpoint_enabled"`
			Bind               string `mapstructure:"bind"`
			APITimingHistogram bool   `mapstructure:"api_timing_histogram"`
		} `mapstructure:"prometheus"`
	} `mapstructure:"metrics"`
}

// IntegrationMQTTConfig holds the configuration for the MQTT integration.
type IntegrationMQTTConfig struct {
	Client IntegrationMQTTClientConfig `mapstructure:"client"`

	Server               string        `mapstructure:"server"`
	Username             string        `mapstructure:"username"`
	Password             string        `mapstructure:"password"`
	MaxReconnectInterval time.Duration `mapstructure:"max_reconnect_interval"`
	QOS                  uint8         `mapstructure:"qos"`
	CleanSession         bool          `mapstructure:"clean_session"`
	ClientID             string        `mapstructure:"client_id"`
	CACert               string        `mapstructure:"ca_cert"`
	TLSCert              string        `mapstructure:"tls_cert"`
	TLSKey               string        `mapstructure:"tls_key"`
	EventTopicTemplate   string        `mapstructure:"event_topic_template"`
	CommandTopicTemplate string        `mapstructure:"command_topic_template"`
	RetainEvents         bool          `mapstructure:"retain_events"`

	// For backards compatibility
	UplinkTopicTemplate        string `mapstructure:"uplink_topic_template"`
	DownlinkTopicTemplate      string `mapstructure:"downlink_topic_template"`
	JoinTopicTemplate          string `mapstructure:"join_topic_template"`
	AckTopicTemplate           string `mapstructure:"ack_topic_template"`
	ErrorTopicTemplate         string `mapstructure:"error_topic_template"`
	StatusTopicTemplate        string `mapstructure:"status_topic_template"`
	LocationTopicTemplate      string `mapstructure:"location_topic_template"`
	TxAckTopicTemplate         string `mapstructure:"tx_ack_topic_template"`
	IntegrationTopicTemplate   string `mapstructure:"integration_topic_template"`
	UplinkRetainedMessage      bool   `mapstructure:"uplink_retained_message"`
	JoinRetainedMessage        bool   `mapstructure:"join_retained_message"`
	AckRetainedMessage         bool   `mapstructure:"ack_retained_message"`
	ErrorRetainedMessage       bool   `mapstructure:"error_retained_message"`
	StatusRetainedMessage      bool   `mapstructure:"status_retained_message"`
	LocationRetainedMessage    bool   `mapstructure:"location_retained_message"`
	TxAckRetainedMessage       bool   `mapstructure:"tx_ack_retained_message"`
	IntegrationRetainedMessage bool   `mapstructure:"integration_retained_message"`
}

// IntegrationMQTTClientConfig holds the additional client config.
type IntegrationMQTTClientConfig struct {
	CACert             string        `mapstructure:"ca_cert"`
	CAKey              string        `mapstructure:"ca_key"`
	ClientCertLifetime time.Duration `mapstructure:"client_cert_lifetime"`
}

// AzurePublishMode defines the publish-mode type.
type AzurePublishMode string

// C holds the global configuration.
var C Config

// Get returns the configuration.
func Get() *Config {
	return &C
}
